FolderTree = function (controllerId, clientId, uniqueId, expandImage, collapseImage, noExpandImage) {
	this._clientId = clientId;
	this._uniqueId = uniqueId;
	this._expandImage = expandImage;
	this._collapseImage = collapseImage;
	this._noExpandImage = noExpandImage;
	this._selectedNode = null;
    this._controller = eval('WFM_' + controllerId);
}

FolderTree.prototype = {
	getController : function() {return this._controller;},
	
	ToggleExpand : function (nodeId) {
		this._ToggleExpand(nodeId, this.PopulateCallback, null, this.PopulateError);
	},
	
	_ToggleExpand : function (nodeId, eventCallback, externalContext, errorCallback) {
		var node = this._getNode (nodeId);
		if(!node) return true;

		var nodeSpan = this._getChildNodesSpan (nodeId);
		var expand = node._expand || node._refresh || nodeSpan.style.display == "none";

		if(expand && node._populating) return false;
		
		if (node._refresh || (nodeSpan.style.display == "none" && nodeSpan.innerHTML.length == 0)) {
			node._populating = true;
			var nodePath = node.attributes["nodepath"].value;
			this.PopulateNode (nodePath, eventCallback, {'folderTree':this,'node':node,'nodeSpan':nodeSpan,'nodeId':nodeId,'nodePath':nodePath,'externalContext':externalContext}, errorCallback);
			return false;
		}
		
		node._expand = false;
		
		var image = this._getNodeImg (nodeId);
		if(nodeSpan.innerHTML == "*") {
			image.src = this._noExpandImage;
			nodeSpan.style.display = "none";
		} else {
			nodeSpan.style.display = expand ? "block" : "none";
			image.src = expand ? this._collapseImage : this._expandImage;
		}
		return true;
	},

	PopulateError : function (data, ctx){
		ctx.folderTree.PopulateCallback (data, ctx);
	},

	PopulateCallback : function (data, ctx)
	{
		ctx.node._refresh = false;
		ctx.node._populating = false;
		if(data == "*")
			ctx.nodeSpan.style.display = "none";
		ctx.nodeSpan.innerHTML = data;
		ctx.folderTree._ToggleExpand (ctx.nodeId, null, null, null);
	},
	
	Navigate : function (nodes, n) {
		for(var i=n; i<nodes.length-1; i++) {
			var node = this._getNode (nodes[i]);
			if (!node) return;
			if(!node._refresh) {
				var nodeSpan = this._getChildNodesSpan (nodes[i]);
				if (nodeSpan.style.display == "block") continue;
				if (nodeSpan.innerHTML == "*") return;
			}
			if(!this._ToggleExpand(nodes[i], this.NavigateCallback, {'nodes':nodes,'index':i}, this.PopulateError)) return;
		}
		var nodeId = nodes[nodes.length-1];
		var node = this._getNode (nodeId);
		if(!node) return;
		this.SelectNode (nodeId);
		if(node._refresh)
			this.Refresh (nodeId);
	},

	NavigateCallback : function (data, ctx)
	{
		ctx.folderTree.PopulateCallback (data, ctx);
		var interval = window.setInterval(function() {
			window.clearInterval(interval);
			ctx.folderTree.Navigate (ctx.externalContext.nodes, ctx.externalContext.index);
		}, 0);
	},
	
	Refresh : function (nodeId) {
		var node = this._getNode (nodeId);
		if(!node) return;
		var nodeSpan = this._getChildNodesSpan (nodeId);
		var expand = nodeSpan.style.display == "block" || nodeSpan.innerHTML == "*";
		
		if(expand) {
			node._expand = true;
			node._refresh = true;
			this.ToggleExpand (nodeId);
		} else {
			nodeSpan.innerHTML = "";
			nodeSpan.style.display = "none"
		}
	},
	
	RequireRefresh : function (nodes) {
		for(var i=0; i<nodes.length; i++) {
			var node = this._getNode (nodes[i]);
			if(!node) continue;
			node._expand = true;
			node._refresh = true;
		}
	},
	
	_getNode : function (nodeId) {
		var id = this._clientId + "_" + nodeId + "_node";
		return WebForm_GetElementById (id);
	},
	
	_getNodeImg : function (nodeId) {
		var imgId = this._clientId + "_" + nodeId + "_img";
		return WebForm_GetElementById (imgId);
	},
	
	_getChildNodesSpan : function (nodeId) {
		var spanId = this._clientId + "_" + nodeId + "_span";
		return WebForm_GetElementById (spanId);
	},
	
	_getNodeLink : function (node) { return node.childNodes[node.childNodes.length - 1]; },
	
	_getImageLink : function (node) { return node.previousSibling.childNodes[node.childNodes.length - 1]; },

	SelectNode : function (nodeId) {
		var node = this._getNode (nodeId);
		if(!node) return;
		if(node === this._selectedNode)
			return;
		
		if(this._selectedNode !== null)
			this._restoreStyle (this._selectedNode);
		
		this._selectedNode = node;
		this._appendStyle (node, this._selectedClass, this._selectedLinkClass);	
	},
	
	HoverNode : function (div, e) {
		var e = e || window.event;
		var node = WebForm_GetElementById (div.id+"_node");
		if(this.getController().isDragging()) {
			var ftNode = this._getFolderTreeNode (div);
			ftNode.onDragInTarget(e);
		}
		else {
			if(node === this._selectedNode)
				return;
			this._appendStyle (node, this._hoverClass, this._hoverLinkClass);
		}
	},

	UnhoverNode : function (div) {
		var node = WebForm_GetElementById (div.id+"_node");
		if(this.getController().isDragging()) {
			var ftNode = this._getFolderTreeNode (div);
			ftNode.onDragLeaveTarget();
		}
		else {
			if(node === this._selectedNode)
				return;
			this._restoreStyle (node);
		}
	},
	
	_getFolderTreeNode : function(div) {
		if(!div._folderTreeNode) {
			div._folderTreeNode = new FolderTreeNode (this, div);
		}
		return div._folderTreeNode;
	},
	
	_appendStyle : function (node, nodeClass, nodeLinkClass) {
		if (nodeClass) {
			if (!node._normalClass)
				node._normalClass = node.className;
			node.className = node._normalClass + " " + nodeClass;
		}
		if (nodeLinkClass) {
			var nodeLink = this._getNodeLink(node);
			if(!nodeLink) return;
			if (!nodeLink._normalClass)
				nodeLink._normalClass = nodeLink.className;
			nodeLink.className = nodeLink._normalClass + " " + nodeLinkClass;
		}
	},

	_restoreStyle : function (node) {
		if (node._normalClass)
			node.className = node._normalClass;
		var nodeLink = this._getNodeLink(node);
		if (nodeLink && nodeLink._normalClass)
			nodeLink.className = nodeLink._normalClass;
	}
}

FolderTreeNode = function(owner, div) {
	this._owner = owner;
	this._div = div;
	this._node = WebForm_GetElementById (div.id+"_node");
	
	var mouseUp = this._mouseUp;
	var mouseMove = this._mouseMove;
	var instance = this;
	div.onmouseup = function(e) {
		e = e || window.event;
		mouseUp.call(instance, e); 
	}
	div.onmousemove = function(e) {
		e = e || window.event;
		mouseMove.call(instance, e);
	}
}

FolderTreeNode.prototype._owner = null;
FolderTreeNode.prototype._div = null;
FolderTreeNode.prototype._dropMove = true;
FolderTreeNode.prototype._node = null;
FolderTreeNode.prototype._highlight = false;
FolderTreeNode.prototype._cursor = null;

FolderTreeNode.prototype.getFullPath = function() {
	var nodePath = "" + this._node.attributes["nodepath"].value;
	var index = nodePath.indexOf("|");
	return nodePath.substring(index+1, nodePath.length);
}

FolderTreeNode.prototype.isSelected = function() {
	return this._node === this._owner._selectedNode;
}

FolderTreeNode.prototype.canDrop = function() {
	return !this.isSelected();
}

FolderTreeNode.prototype.getController = function() {return this._owner.getController();}

FolderTreeNode.prototype.highlight = function (bool) {
	if(this._highlight == bool) return;
	this._highlight = bool;
	if(bool) this._owner._appendStyle (this._node, this._owner._selectedClass, this._owner._selectedLinkClass);	
	else this._owner._restoreStyle (this._node);
}

FolderTreeNode.prototype.setCursor = function (cursor) {
	if(this._cursor == cursor) return;
	this._cursor = cursor;
	this._div.style.cursor = cursor;
	var nodeLink = this._owner._getNodeLink(this._node);
	if(nodeLink){
		nodeLink.style.cursor = cursor;
	}
	var imgLink = this._owner._getImageLink(this._node);
	if(imgLink){
		imgLink.style.cursor = cursor;
	}
}
	
FolderTreeNode.prototype._mouseUp = function(ev) {
	if(ev.preventDefault) ev.preventDefault();
	ev.returnValue = false;
	if(this.getController().isDragging())
		this.onDrop();
	return false;
}

FolderTreeNode.prototype._mouseMove = function(ev) {
	if(ev.preventDefault) ev.preventDefault();
	ev.returnValue = false;
	if(this.getController().isDragging())
		this.onDragInTarget(ev);
	return false;
}

FolderTreeNode.prototype.onDragInTarget = function (ev){
	if(this.canDrop()){
		this._dropMove = !ev.ctrlKey && !ev.shiftKey;
		this.getController()._dropTarget = this;
		this.highlight(true);
		if(this._dropMove)
			this.setCursor(this.getController()._dropMoveCursor);
		else
			this.setCursor(this.getController()._dropCopyCursor);
	}
	else {
		this.setCursor(this.getController()._dropNotAllowedCursor);
	}
}

FolderTreeNode.prototype.onDragLeaveTarget = function (){
	this.getController()._dropTarget = null;
	if(this.canDrop()){
		this.highlight(false);
	}
	this.setCursor("");
}

FolderTreeNode.prototype.onDrop = function (){
	if(this.canDrop()) {
		this.getController().drop(this, this._dropMove);
		this.highlight(false);
	}
	else {
		this.getController().stopDragDrop(this);
	}
	this.setCursor("");
}
